﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using NUnit.Framework;
using QuickBencher.Repositories;

namespace QuickBencher.Test
{
    public class HtmlReportPrinterTests
    {
        [TestFixture]
        public class When_print
        {
            private CustomHtmlReportPrinter printer;

            [SetUp]
            public void Setup()
            {
                printer = new CustomHtmlReportPrinter();
            }

			[TearDown]
			public void Teardown()
			{
				//Set back to default
				Printers.UsePrinter(new ConsolePrinter());
			}

            [Test]
            [ExpectedException(typeof(ArgumentNullException))]
            public void Then_assure_arg_is_validated_for_NullObjs()
            {
                printer.Print(null);
            }

            [Test]
            [ExpectedException(typeof(ArgumentException))]
            public void Then_assure_Exception_is_thrown_if_arg_is_not_of_type_Measure()
            {
                printer.Print("hello world");
            }

        	[Test]
        	public void Then_assure_Printet_Measurement_is_persisted()
        	{
        		var measurementsToPrint = new List<Measurement>();
        		measurementsToPrint.Add(new Measurement{ Label = "Hello world"});
				measurementsToPrint.Add(new Measurement{ Label = "New measurement" });

        		foreach (var measurement in measurementsToPrint)
        		{
        			printer.Print(measurement);
        		}

				Assert.AreEqual(measurementsToPrint.Count, printer.MeasurementRepositoryFake.PersistedMeasurements.Count);
        	}

        	[Test]
        	public void Then_assure_Html_is_generated()
        	{
				var quickBencherDir = HtmlReportPrinter.QuickBencherDir;
        		var htmlReportFilePath = Path.Combine(quickBencherDir, "Report.html");

				printer.Print(new Measurement{ Label = "Test" });

				Assert.IsTrue(File.Exists(htmlReportFilePath));
        	}

        	[Test]
        	public void Then_assure_stylesheet_is_generated()
        	{
        		var cssFilePath = Path.Combine(HtmlReportPrinter.QuickBencherDir, "css\\default.css");
				printer.Print(new Measurement{ Label = "Test" });

				Assert.IsTrue(File.Exists(cssFilePath));
        	}

        	[Test]
        	public void Then_assure_script_is_generated()
        	{
        		var quickBencherJs = Path.Combine(HtmlReportPrinter.QuickBencherDir, "scripts\\quickbencher.js");
        		var jqueryJs = Path.Combine(HtmlReportPrinter.QuickBencherDir, "scripts\\jquery-1.4.2.js");
        		var jqueryFlotJs = Path.Combine(HtmlReportPrinter.QuickBencherDir, "scripts\\jquery.flot.js");

				printer.Print(new Measurement{ Label = "Test"});

				Assert.IsTrue(File.Exists(quickBencherJs));
				Assert.IsTrue(File.Exists(jqueryJs));
				Assert.IsTrue(File.Exists(jqueryFlotJs));
        	}

        	[Test]
        	public void Then_assure_WebPage_is_displayed_if_user_asked_it()
        	{
        		printer.DisplayWebPage = true;
				
				printer.Print(new Measurement{ Label = "Hello" });

				Assert.IsTrue(printer.WasWebPageDisplayed);
        	}

        	[Test]
        	public void Then_assure_WebPage_is_not_displayed_if_user_did_not_ask_it()
        	{
        		printer.DisplayWebPage = false;

				printer.Print(new Measurement{ Label = "Hello" });

				Assert.IsFalse(printer.WasWebPageDisplayed);
        	}
        }

		[TestFixture]
		public class When_integrated
		{
			[Test]
			[Ignore("Should only be executed on demand")]
			public void Then_verify_it_works()
			{
				Printers.UsePrinter(new HtmlReportPrinter{ DisplayWebPage = true });

				Benchmark.Measure("Create many:Person objects", () =>
				{
					var persons = new List<Person>();
					for (int i = 0; i < 10000000; i++)
					{
						persons.Add(new Person { Name = "goeran" });
					}
				});
			}

			private class Person
			{
				public string Name { get; set; }
			}
		}

		class CustomHtmlReportPrinter : HtmlReportPrinter
		{
			public FakeMeasurementRepository MeasurementRepositoryFake = new FakeMeasurementRepository();
			public bool WasWebPageDisplayed { get; set; }

			protected override MeasurementRepository GetMeasurementRepository()
			{
				return MeasurementRepositoryFake;
			}

			protected override void ShowWebPage()
			{
				WasWebPageDisplayed = true;
			}
		}

		class FakeMeasurementRepository : MeasurementRepository
		{
			public List<Measurement> PersistedMeasurements = new List<Measurement>();

			public override void Save(Measurement measurement)
			{
				PersistedMeasurements.Add(measurement);
			}
		}


    }
}
